package com.om39a.plm.crawler;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;

import com.om39a.plm.exceptions.PageLoadFailedException;
import com.om39a.plm.service.HttpClientFactory;
import com.om39a.plm.service.PLMService;
import com.om39a.plm.utils.PLMConstants;
import com.om39a.plm.utils.PLMUtils;

public abstract class PLMBrowser {

	static Logger logger = Logger.getLogger(PLMBrowser.class);

	private HttpClient httpClient = HttpClientFactory.getDefaultInstance();

	private int[] randonTimeInMills = new int[] { 10000, 12000, 14000, 16000,
			18000, 20000, 22000, 24000, 26000, 28000, 30000 };

	private boolean[] randonLogin = new boolean[] { true, false, false, true,
			false, true, true, false, false, false, true };

	private static Map<String, String> userDetails = new HashMap<String, String>();

	private static Random r = new Random();

	public PLMBrowser() {
		userDetails.put("hollypatrick3265", "punnakku");
		userDetails.put("wendywhite3265", "punnakku");
		userDetails.put("patriciapatrick3265", "punnakku");
	}

	public String execute(String url) throws PageLoadFailedException {
		logger.info("Entering into execute - " + url);

		login();

		try {
			Thread.sleep(randonTimeInMills[r.nextInt(10)]);
		} catch (InterruptedException e) {
			e.printStackTrace();
			logger.info(e);
		}
		// Forum URL will be given by the user
		String mainForumURL = PLMUtils.appendBaseURL(url);
		String mainForumContent = openPage(mainForumURL);
		logger.info("Exiting from execute");
		return mainForumContent;

	}

	private void login() {

		if (randonLogin[r.nextInt(10)]) {

			resume1: {

				Random random = new Random();
				List<String> keys = new ArrayList<String>(userDetails.keySet());
				String randomUserId = keys.get(random.nextInt(keys.size()));
				String randonPassword = userDetails.get(randomUserId);

				Map<String, String> loginArgs = new HashMap<String, String>();

				loginArgs.put(PLMConstants.USER_NAME, randomUserId);
				loginArgs.put(PLMConstants.PASSWORD, randonPassword);

				System.out.println("Logging in with " + randomUserId + "-:-"
						+ randonPassword);

				if (PLMService.getInstance().login(loginArgs)) {
					logger.info("Login Success- " + loginArgs);
				} else {
					logger.info("Login Failed- " + loginArgs);
					break resume1;
				}
			}

		}
	}

	public String execute(String url, Map<String, String> args)
			throws PageLoadFailedException {
		logger.info("Exiting from execute - " + url + " - " + args);
		throw new PageLoadFailedException(
				"Page loading failed. Page loading not supported for this class");
	}

	/**
	 * Used to just execute the page without getting the page source. User for
	 * executing login requests
	 * 
	 * @param url
	 * @param nvps
	 * @return
	 * @throws PageLoadFailedException
	 */
	public String openPage(String url, List<NameValuePair> nvps)
			throws PageLoadFailedException {
		logger.info("Exiting from openPage - " + url + " - " + nvps);
		StringBuffer content = new StringBuffer();
		// Creating a post request for the login page
		HttpPost httpPost = new HttpPost(url);
		try {
			// Encoding the post requests
			httpPost.setEntity(new UrlEncodedFormEntity(nvps));
			// Executing the post request
			HttpResponse response = httpClient.execute(httpPost);
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode <= 200 && statusCode >= 399) {
				throw new PageLoadFailedException(
						"Page loading failed during a post request");
			}
			// Login success
			HttpEntity entity = response.getEntity();
			BufferedReader reader = new BufferedReader(new InputStreamReader(
					entity.getContent()));
			String line = "";
			// writing contents of the file to temporary buffer
			while ((line = reader.readLine()) != null) {
				content.append(line);
			}
			EntityUtils.consume(entity);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			logger.info(e);
		} catch (ClientProtocolException e) {
			e.printStackTrace();
			logger.info(e);
		} catch (IOException e) {
			e.printStackTrace();
			logger.info(e);
		} catch (Exception e) {
			e.printStackTrace();
			logger.info(e);
		} finally {
			httpPost.releaseConnection();
		}
		logger.info("Exiting from openPage");
		return content.toString();
	}

	/**
	 * Used to execute the page by getting the contents of the page as a string
	 * 
	 * @param url
	 * @throws PageLoadFailedException
	 */
	public String openPage(String url) throws PageLoadFailedException {
		logger.info("Exiting from openPage - " + url);
		StringBuffer content = new StringBuffer();
		// Loading the URL give as method query
		HttpGet httpGet = new HttpGet(url);
		logger.info("Loading the URL " + url);
		try {
			HttpResponse response = httpClient.execute(httpGet);
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode <= 200 && statusCode >= 399) {
				throw new PageLoadFailedException(
						"Page loading failed during a get request");
			}
			HttpEntity entity = response.getEntity();
			BufferedReader reader = new BufferedReader(new InputStreamReader(
					entity.getContent()));
			String line = "";
			// writing contents of the file to temporary buffer
			while ((line = reader.readLine()) != null) {
				content.append(line);
			}
			EntityUtils.consume(entity);
		} catch (ClientProtocolException e) {
			e.printStackTrace();
			logger.info(e);
		} catch (IOException e) {
			e.printStackTrace();
			logger.info(e);
		} catch (Exception e) {
			e.printStackTrace();
			logger.info(e);
		} finally {
			httpGet.releaseConnection();
		}
		logger.info("Exiting from openPage");
		return content.toString();
	}

}
